﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;

namespace Neatly
{
    public static class HashHelper
    {
        #region MD5
        /// <summary>
        /// 获取字符串的MD5
        /// </summary>
        public static string StringMD5(string str)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(str);
            return BytesMD5(buffer);
        }

        /// <summary>
        /// 获取文件的MD5
        /// </summary>
        public static string FileMD5String(string filePath)
        {
            try
            {
                using FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                return StreamMD5String(fs);
            }
            catch (Exception e)
            {
                Debug.LogError(e);
                return string.Empty;
            }
        }

        public static byte[] FileMD5Bytes(string filePath)
        {
            try
            {
                using FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                return StreamMD5Bytes(fs);
            }
            catch (Exception e)
            {
                Debug.LogError(e);
                return null;
            }
        }

        public static string StreamMD5String(Stream stream)
        {
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] hashBytes = provider.ComputeHash(stream);
            return ToString(hashBytes);
        }

        public static byte[] StreamMD5Bytes(Stream stream)
        {
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] hashBytes = provider.ComputeHash(stream);
            return hashBytes;
        }

        private static string ToString(byte[] hashBytes)
        {
            string result = BitConverter.ToString(hashBytes);
            result = result.Replace("-", "");
            return result.ToLower();
        }

        /// <summary>
        /// 获取字节数组的MD5
        /// </summary>
        public static string BytesMD5(byte[] buffer)
        {
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] hashBytes = provider.ComputeHash(buffer);
            return ToString(hashBytes);
        }
        #endregion
        
        private static readonly StringBuilder HexStringBuilder = new(32);
        private static readonly char[] HEX_CHAR_ARRAY = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        public static string ToHexString(byte[] hashBytes)
        {
            HexStringBuilder.Clear();
            foreach (var b in hashBytes)
            {
                var index1 = b & 0xF0;
                var index2 = b & 0x0F;
                HexStringBuilder.Append(HEX_CHAR_ARRAY[index1 >> 4]);
                HexStringBuilder.Append(HEX_CHAR_ARRAY[index2]);
            }
            return HexStringBuilder.ToString();
        }
    }
}